package com.youlu.campus.service.account.impl;

import com.alibaba.fastjson.JSON;
import com.mongodb.client.result.DeleteResult;
import com.youlu.campus.activity.service.UserActivityQuantityRecordService;
import com.youlu.campus.activity.service.UserActivityTaskRankingService;
import com.youlu.campus.activity.service.UserDailyLearningService;
import com.youlu.campus.base.exception.BusinessException;

import com.youlu.campus.common.utils.SM2CryptUtils;
import com.youlu.campus.entity.OOrderInfo;
import com.youlu.campus.entity.OrderInfo;
import com.youlu.campus.entity.UserBlackList;
import com.youlu.campus.entity.UserInfoExtend;
import com.youlu.campus.entity.UserPO;
import com.youlu.campus.entity.UserParticipateActivityInfo;
import com.youlu.campus.entity.VO.req.WechatWriteOffReq;
import com.youlu.campus.entity.WechatAuthBlackList;
import com.youlu.campus.entity.WechatH5UserPO;
import com.youlu.campus.entity.WechatWriteOffLog;
import com.youlu.campus.service.account.WechatWriteOffLogService;
import com.youlu.campus.service.account.WechatWriteOffService;
import com.youlu.campus.service.activity.UserParticipateActivityInfoService;
import com.youlu.campus.service.cache.CacheUserService;
import com.youlu.campus.service.invite.UserInviteRecordService;
import com.youlu.campus.service.qa.UserQaInfoService;
import com.youlu.campus.service.ranking.UserActivityPointRankingProvinceService;
import com.youlu.campus.service.visitor.UserBlackListService;
import com.youlu.campus.service.visitor.UserInfoExtendService;
import com.youlu.campus.service.wechat.WechatAuthBlackListService;
import com.youlu.campus.service.wechat.WechatH5Service;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
public class WechatWriteOffServiceImpl implements WechatWriteOffService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private WechatAuthBlackListService wechatAuthBlackListService;
    @Autowired
    private WechatH5Service wechatH5Service;
    @Autowired
    private UserInfoExtendService userInfoExtendService;
    @Autowired
    private WechatWriteOffLogService wechatWriteOffLogService;
    @Lazy
    @Autowired
    private CacheUserService cacheUserService;
    @Lazy
    @Autowired
    private UserBlackListService userBlackListService;

    @Autowired
    private UserActivityTaskRankingService userActivityTaskRankingService;

    @Autowired
    private UserActivityPointRankingProvinceService userActivityPointProvinceRankingService;

    @Autowired
    private UserParticipateActivityInfoService userParticipateActivityInfoService;

    @Autowired
    private UserQaInfoService userQaInfoService;

    @Autowired
    private UserInviteRecordService userInviteRecordService;

    @Autowired
    private UserActivityQuantityRecordService userActivityQuantityRecordService;

    @Autowired
    private UserDailyLearningService userDailyLearningService;

    @Override
    public boolean writeOff(WechatWriteOffReq req) {
        log.info(":>>> 开始注销用户:{}", JSON.toJSON(req));
        WechatAuthBlackList wechatAuthBlackList =
                wechatAuthBlackListService.findBySysAppId(req.getSystemAppId());
        if (Objects.isNull(wechatAuthBlackList)) {
            log.error(":>>> 错误注销请求:{} 不存在", req.getSystemAppId());
            return false;
        }
        String decryptUserId = SM2CryptUtils.decrypt(req.getEncUserId(), wechatAuthBlackList.getPrivatekey());
        if (!decryptUserId.equals(req.getUserId())) {
            log.error(":>>> 请求的UserId和系统UserId不相符:{},{}", decryptUserId, req.getUserId());
            throw new BusinessException("非法的注销请求");
        }
        switch (req.getPlatform()) {
            case "wechat-h5":
                this.writeOffWechatH5Account(req);
                break;
            default:
                break;
        }
        return false;
    }

    @Override
    public boolean writeOffWechatH5Account(WechatWriteOffReq req) {
        log.info(":>>> 开始注销WechatH5账号:{}", JSON.toJSON(req));
        Date date = new Date();
        final String userId = req.getUserId();
        List<WechatH5UserPO> wechatH5UserPOS = wechatH5Service.findByUserId(req.getUserId());
        log.info(":>>> 用户:{} 的H5用户个数:{}", req.getUserId(), wechatH5UserPOS == null ? 0 : wechatH5UserPOS.size());
        //
        UserInfoExtend userInfoExtend = userInfoExtendService.findByUserId(userId);
        log.info(":>>> 用户扩展信息为:{}", JSON.toJSON(userInfoExtend));
        Query queryOrders = new Query();
        queryOrders.addCriteria(Criteria.where("accountInfoId").is(userId));
        List<OrderInfo> orderInfos = mongoTemplate.find(queryOrders, OrderInfo.class);
        log.info(":>>> 用户:{},在平台订单的数量:{}", userId, orderInfos == null ? 0 : orderInfos.size());
        Query queryAccount = new Query();
        queryAccount.addCriteria(Criteria.where("id").is(userId));
        UserPO accountInfo = mongoTemplate.findOne(queryAccount, UserPO.class);
        String mobile = "";
        if (StringUtils.isNotBlank(accountInfo.getMobile())) {
            mobile = accountInfo.getMobile();
        } else if (!StringUtils.isNotBlank(mobile) && Objects.nonNull(userInfoExtend)) {
            mobile = userInfoExtend.getMobile();
        }
        WechatWriteOffLog wechatWriteOffLog = new WechatWriteOffLog();
        wechatWriteOffLog.setDate(date);
        wechatWriteOffLog.setCreatedTime(date);
        wechatWriteOffLog.setMobile(mobile);
        wechatWriteOffLog.setIp(req.getIp());
        wechatWriteOffLog.setType("account");
        wechatWriteOffLog.setWriteOffReason(req.getWriteOffReason());
        if (Objects.nonNull(userInfoExtend)) {
            wechatWriteOffLog.setName(userInfoExtend.getName());
            wechatWriteOffLog.setUniversityId(userInfoExtend.getUniversityId());
            wechatWriteOffLog.setUniversityName(userInfoExtend.getUniversityName());
        }
        if (Objects.nonNull(wechatH5UserPOS)) {
            for (WechatH5UserPO wechatH5UserPO : wechatH5UserPOS) {
                if (!StringUtils.isNotBlank(wechatH5UserPO.getAppId())) {
                    continue;
                }
                List<String> openIds = wechatWriteOffLog.getOpenIds().get(wechatH5UserPO.getAppId());
                if (Objects.isNull(openIds)) {
                    openIds = new ArrayList<>();
                }
                openIds.add(wechatH5UserPO.getOpenId());
                wechatWriteOffLog.getOpenIds().put(wechatH5UserPO.getAppId(), openIds);

            }
        }
        wechatWriteOffLog.setUserId(userId);
        wechatWriteOffLog.setOpenId(req.getOpenId());
        wechatWriteOffLog.setOrderNum(orderInfos == null ? 0 : orderInfos.size());
        wechatWriteOffLog.setAppId(req.getAppId());
        wechatWriteOffLog = wechatWriteOffLogService.create(wechatWriteOffLog);
        // 加入黑名单
        try {
            UserBlackList ubl = new UserBlackList();
            ubl.setOptUser("zhuhuaiqi");
            ubl.setOptWay("1");
            ubl.setMobile(mobile);
            if (Objects.nonNull(userInfoExtend)) {
                ubl.setName(userInfoExtend.getName());
                ubl.setUniversityId(userInfoExtend.getUniversityId());
                ubl.setUniversityName(userInfoExtend.getUniversityName());
            }
            ubl.setType("10");
            ubl.setLimitType("2");
            ubl.setComments("用户自动注销");
            userBlackListService.create(ubl);
        } catch (Exception e) {
            log.error(":>>> 自动注销添加黑名单异常:{}", e);
        }
        // 删除用户报名信息
        this.deleteUserParticipateActivityInfo(userId);
        // 注销订单信息
        deleteOrders(orderInfos, userId,
                wechatWriteOffLog.getId(), date);
        // 删除WechatH5
        wechatH5Service.deleteByUserId(userId);
        // 删除用户扩展信息
        userInfoExtendService.deleteByUserId(userId);
        // 删除账号信息
        this.deleteAccountInfo(userId);
        // 删除订阅消息
        wechatH5Service.deleteMiniUser(userId);

        return true;
    }

    @Override
    public boolean writeOffActivity(WechatWriteOffReq req) {
        log.info(":>>> 开始注销WechatH5活动:{}", JSON.toJSON(req));
        Date date = new Date();
        final String userId = req.getUserId();
        List<WechatH5UserPO> wechatH5UserPOS = wechatH5Service.findByUserId(req.getUserId());
        log.info(":>>> 用户:{} 的H5用户个数:{}", req.getUserId(), wechatH5UserPOS == null ? 0 : wechatH5UserPOS.size());
        //
        UserInfoExtend userInfoExtend = userInfoExtendService.findByUserId(userId);
        log.info(":>>> 用户扩展信息为:{}", JSON.toJSON(userInfoExtend));
        Query queryOrders = new Query();
        queryOrders.addCriteria(Criteria.where("accountInfoId").is(userId));
        List<OrderInfo> orderInfos = mongoTemplate.find(queryOrders, OrderInfo.class);
        log.info(":>>> 用户:{},在平台订单的数量:{}", userId, orderInfos == null ? 0 : orderInfos.size());
        Query queryAccount = new Query();
        queryAccount.addCriteria(Criteria.where("id").is(userId));
        UserPO accountInfo = mongoTemplate.findOne(queryAccount, UserPO.class);
        String mobile = "";
        if (StringUtils.isNotBlank(accountInfo.getMobile())) {
            mobile = accountInfo.getMobile();
        } else if (!StringUtils.isNotBlank(mobile) && Objects.nonNull(userInfoExtend)) {
            mobile = userInfoExtend.getMobile();
        }
        WechatWriteOffLog wechatWriteOffLog = new WechatWriteOffLog();
        wechatWriteOffLog.setDate(date);
        wechatWriteOffLog.setCreatedTime(date);
        wechatWriteOffLog.setMobile(mobile);
        wechatWriteOffLog.setIp(req.getIp());
        wechatWriteOffLog.setType("activity");
        wechatWriteOffLog.setWriteOffReason(req.getWriteOffReason());
        if (Objects.nonNull(userInfoExtend)) {
            wechatWriteOffLog.setName(userInfoExtend.getName());
            wechatWriteOffLog.setUniversityId(userInfoExtend.getUniversityId());
            wechatWriteOffLog.setUniversityName(userInfoExtend.getUniversityName());
        }
        if (Objects.nonNull(wechatH5UserPOS)) {
            for (WechatH5UserPO wechatH5UserPO : wechatH5UserPOS) {
                if (!StringUtils.isNotBlank(wechatH5UserPO.getAppId())) {
                    continue;
                }
                List<String> openIds = wechatWriteOffLog.getOpenIds().get(wechatH5UserPO.getAppId());
                if (Objects.isNull(openIds)) {
                    openIds = new ArrayList<>();
                }
                openIds.add(wechatH5UserPO.getOpenId());
                wechatWriteOffLog.getOpenIds().put(wechatH5UserPO.getAppId(), openIds);
            }
        }
        wechatWriteOffLog.setUserId(userId);
        wechatWriteOffLog.setOpenId(req.getOpenId());
        wechatWriteOffLog.setOrderNum(orderInfos == null ? 0 : orderInfos.size());
        wechatWriteOffLog.setAppId(req.getAppId());
        wechatWriteOffLogService.create(wechatWriteOffLog);
        // 删除用户报名信息
        this.deleteUserParticipateActivityId(userId, req.getActivityId());
        return true;
    }

    /**
     * 删除用户报名信息
     *
     * @param userId
     * @return
     */
    private boolean deleteUserParticipateActivityInfo(String userId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(userId));
        DeleteResult deleteResult = mongoTemplate.remove(query, UserParticipateActivityInfo.class);
        log.info(":>>> 删除用户:{} 报名信息数量:{}", userId, deleteResult.getDeletedCount());
        return deleteResult.getDeletedCount() > 0 ? true : false;
    }

    /**
     * 删除用户报名活动信息
     *
     * @param userId
     * @return
     */
    private boolean deleteUserParticipateActivityId(String userId, String activityId) {
        if (StringUtils.isBlank(userId) || StringUtils.isBlank(activityId)) {
            return false;
        }
        //删除用户报名信息
        userParticipateActivityInfoService.deleteByUserIdAndActivityId(userId, activityId);
        //删除排行榜记录
        userActivityTaskRankingService.deleteByUserIdAndActivityId(userId, activityId);
        //删除省份积分
        userActivityPointProvinceRankingService.deleteByUserIdAndActivityId(userId, activityId);
        //删除用户答题信息
        userQaInfoService.deleteByUserIdAndActivityId(userId, activityId);
        //删除用户邀请信息
        userInviteRecordService.deleteByInvitedByUserIdAndActivityId(userId, activityId);
        //贡献值记录
        userActivityQuantityRecordService.deleteByUserIdAndActivityId(userId, activityId);
        //删除用户签到记录
        userDailyLearningService.deleteByUserIdAndActivityId(userId, activityId);
        return true;
    }

    /**
     * 删除用户订单信息
     *
     * @param userId
     * @return
     */
    private boolean deleteOrders(List<OrderInfo> orderInfos, String userId,
                                 String taskId, Date date) {
        if (Objects.isNull(orderInfos)) {
            return false;
        }
        for (OrderInfo orderInfo : orderInfos) {
            Query query = new Query();
            query.addCriteria(Criteria.where("id").is(orderInfo.getId()));
            Update update = new Update();
            update.set("writeOffed", Boolean.TRUE);
            update.set("updatedTime", date);
            update.set("writeTaskId", taskId);
            mongoTemplate.updateFirst(query, update, OrderInfo.class);
            Query querySub = new Query();
            querySub.addCriteria(Criteria.where("orderNo").is(orderInfo.getOrderNo()));
            Update updateSub = new Update();
            updateSub.set("writeOffed", Boolean.TRUE);
            updateSub.set("updatedTime", date);
            updateSub.set("writeTaskId", taskId);
            mongoTemplate.updateFirst(querySub, updateSub, OOrderInfo.class);
        }
        return true;
    }

    private boolean deleteAccountInfo(String userId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(userId));
        DeleteResult deleteResult = mongoTemplate.remove(query, UserPO.class);
        log.info(":>>> 用户:{} 账号信息数量:{}", userId, deleteResult.getDeletedCount());
        cacheUserService.removeUserId(userId);
        return deleteResult.getDeletedCount() > 0 ? true : false;
    }
}
